#include <18F2550.h>

//seccion de configuracion del microcontrolador
#fuses NOMCLR        // Pin MCLR como entrada digital RE3.
#fuses HSPLL         // Cristal HS + PLL.
#fuses NOWDT         // No activamos el WatchDog.
#fuses NOPROTECT     // No activamos la protección contra lecturas.
#fuses NOLVP         // No activamos el modo de programación a bajo voltaje.
#fuses NODEBUG       // No incluimos código para debug.
#fuses USBDIV        // 96Mhz del PLL/2 = 48Mhz para USB en Full speed.
#fuses PLL5          // Factor de división de la entrada del PLL = 1 para 4mhz.
#fuses CPUDIV1       // El PLL postscaler decide la división en 2 de la frecuencia de salida del PLL de 96MHZ.
#fuses VREGEN      // Desactivamos el regulador de 3.3v del puerto USB.
#fuses NOPBADEN      // Puerto B como I/O digital.
#use delay(clock=48000000) // Frecuencia de trabajo 48Mhz.


//seccion de inclusion de librerias
#include "flex_lcd.c"
#include "usb_cdc.h"
#include "usb_desc_cdc.h"
#include <string.h>
#include <stdlib.h>

//Definiciones para seleccionar esclavos
#define SLAVE1 PIN_C0
#define SLAVE2 PIN_C1
#define dmas   PIN_C5
#define dmenos PIN_C4
#define SSLAVE1 output_high(SLAVE1);
#define SSLAVE2 output_high(SLAVE2);

//Definiciones de variables globales
int const lenbuff=10; //tama�o del buffer para recibir la instrucci�n
int xbuff=0; //Este es el indice, siguiente caracter en el buffer
char cbuff[lenbuff]; //Buffer de recepci�n
int1 flagcommand; //bandera para saber si presionamos enter
char rcvchar= 0x00; //ultimo caracter recibido  <--- Declaracion


//prototipos
void command_process();
void add2cbuff(char c);
void echosel(char c);
void command_menu(void);
void enviadatospi(unsigned int slave, unsigned char dato);


void serial_isr(void){  // interrupcion serial usart

      rcvchar=usb_cdc_getc(); //se carga a la variable rcvchar
      add2cbuff(rcvchar); //y se agrega al buffer
      echosel(rcvchar); //hacer un eco selectivo

 }

void main(void)
{
   

   //inicializaciones
   output_low(SLAVE2);
   output_low(SLAVE1);
   output_low(dmas);
   output_low(dmenos);
   lcd_init();
   usb_cdc_init();
   usb_init();

   printf(lcd_putc,"Conectar a USB\n\r");
   delay_ms(2300);
   setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_16|SPI_SS_DISABLED);

   lcd_putc("\f");
   while(!usb_cdc_connected())   //mientras no se conecte
   {
      lcd_gotoxy(1,1);printf(lcd_putc,"Aun no USB");
   }
   lcd_putc("\f");
   printf(lcd_putc,"USB conectado\n\r");
//-----------------
   while(TRUE)
   {
   usb_task();
   if(usb_enumerated())
   {   
   command_menu();
      while(TRUE)
     {
	do{
	if(usb_cdc_kbhit())
	{
		serial_isr();
	}
	}while(flagcommand=='\0');

	if(flagcommand!='\0')
	{
        command_process();
	}
	else
	{
	flagcommand='\0';
	}
      }
   }
   }
   
//------------------
}





void enviadatospi(unsigned int slave, unsigned char dato)
{

         output_high(slave);
         spi_write(dato);
         output_low(slave);
         delay_us(100);
         output_high(slave);
         delay_us(100);
         output_low(slave);
         break;
   }


void initBuff(void){
   int i=0;
   for (i=0; i< lenbuff;i++){
         cbuff[i]=0x0;
      }xbuff=0x00;
}


//agrega un caracter mas al buffer, o realiza un acci�n
void add2cbuff(char c){
if(xbuff<lenbuff){  //A�ade caracteres al buffer mientras no se llene el buffer
   switch(c){
   case 0x0D: //Enter  --> Habilita flag para procesar comando
            flagcommand=1;
            break;
   case 0x08: //BackSpace --> Borra del buffer el ultimo caracter insertado
            if(xbuff>0) cbuff[--xbuff]=0x00;
            break;
   case 0x1B: //ESC  --> Borra todo el buffer
            initBuff();
            break;
   default:  //a�ade caracter al buffer recibido
         cbuff[xbuff++]=c;
   }
}
else{
initBuff();//Si el buffer esta lleno, vacialo
printf(usb_cdc_putc,"Buff. Lleno\r\n");  //Envia mensaje de que el buffer esta lleno
}
}

//Solo imprime los caracteres imprimibles
void echosel(char c){
switch(c){
      case 0x0D: //Si presionamos la tecla intro
     // printf("\r\n[ENT]\r\n ");
      break;
      case 0x08: //Si presionamos la tecla BackSpace
     // printf("\r\n [BACK]\r\n");
      break;
      case 0x1B: //Si presionamos la tecla ESC
     // printf("\r\n[ESC]\r\n");
      break;
      default:
      usb_cdc_putc(c); //Echo de cualquier otro caracter
   }
}

//Procesador de comandos
void command_menu(void){
printf(usb_cdc_putc,"Comunicaciones\r\n");
printf(usb_cdc_putc,"Metodo: Recibiendo sobre el buffer\r\n\n");
printf(usb_cdc_putc,"\r\n\r\n");
}

void command_process(void){

/*
El formato de los comandos es el siguiente:
[a...e] [123] [xx]
servo posicion velocidad
primer byte un caracter alfab�tico de entre a y e que define al servo
tres bytes para definir la posicion del servo
dos bytes para definir la velocidad de movimiento del servo
a12301 {enter}
mueve el servo 1 a 123 grados de la posicion de origen a la velocidad 01
*/
   int16 i;
   char cmd[lenbuff]; //comando tecleado
   char servo[2];
   char pos[4];  //para almacenar las posiciones
   int8 posicion;
   char velocidad[4];  //para almacenar los incrementos
   int8 vel;
   
   flagcommand=0; //Es desactivada la flag cuando el comando esta pendiente
   printf(lcd_putc,"\f%c*%c%c%c*%c%c",cbuff[0], cbuff[1], cbuff[2], cbuff[3],cbuff[4],cbuff[5]);
   printf(usb_cdc_putc,"\n\r%c*%c%c%c*%c%c",cbuff[0], cbuff[1], cbuff[2], cbuff[3],cbuff[4],cbuff[5]);
   printf(usb_cdc_putc,"\nprocesando ...\r\n");
   
   strcpy(cmd,cbuff); //hacer la copia para procesar y almacenar variables
   strncpy(servo,cbuff,1);
   printf(usb_cdc_putc,"servo: - %s - \r\n",servo);

   //guarda la posicion del servo
   strcpy(cmd,cbuff); 
   for(i=1;i<4;i++){
   pos[i-1]= cmd[i];
   }
   posicion = atoi(pos);
   printf(usb_cdc_putc,"pos: %u \r\n",posicion);
   
   //guarda la velocidad con la que se mover� el servo
   strcpy(cmd,cbuff);
   for(i=4;i<7;i++)
   {
   velocidad[i-4]=cmd[i];
   }
   vel = atoi(velocidad);
   printf(usb_cdc_putc,"vel: %u\r\n", vel);
   //Esta condicional sirve para asignar el valor del valor inicial
   //ke en diferencia con el valor final moveran al servo en 
   //uno o en otro sentido.
   switch(cbuff[0]){
   case 'A':
            //posI = servo_PWM[0];
		printf(lcd_putc,"\fenvio S1");
		enviadatospi(31760,pos);   //Esto viene del archivo 18f2550.h
		enviadatospi(31760,vel);	//#define PIN_C0  31760 
		printf(lcd_putc,"\ndato enviado");
            break;
   case 'B':
            //posI = servo_PWM[1];
		printf(lcd_putc,"\fenvio S2");
		enviadatospi(31761,pos);
		enviadatospi(31761,vel);
		printf(lcd_putc,"\ndato enviado");
            break;
   case 'C':
            //posI = servo_PWM[2];
		printf(lcd_putc,"\fenvio S3");
            break;
   case 'D':
            //posI = servo_PWM[3];
		printf(lcd_putc,"\fenvio S4");
            break;
   case 'E':
            //posI = servo_PWM[4];
		printf(lcd_putc,"\fenvio S5");
            break;
   case 'F':
            //posI = servo_PWM[4];
		printf(lcd_putc,"\fenvio S6");
            break;
   default:
            printf(usb_cdc_putc,"opcion no valida vuelve a intentar\r\n");
            break;
   }
   initBuff();  //inicializamos el buffer
   printf(usb_cdc_putc,"Procesado\r\n\r\n");
   }

